//#include "stdio.h"        // C++中建议使用C++标准库而非C库
#include <sys/socket.h>     // 包含socket()、bind()、connect()等函数声明
#include <netinet/in.h>     // 包含AF_INET、SOCK_STREAM等常量定义
#include <arpa/inet.h>      // 包含inet_addr()等IP地址处理函数（如果需要）
#include <unistd.h>         // 包含close()函数

#include <cstdio>
#include <cstring>          // 提供std::strerror
#include <string>
using std::string;

inline bool ret_check(int ret, const string& msg = "", bool should_exit = true)
    { 
        if(ret < 0){
            char message[256];
            
            snprintf(message, sizeof(message), 
                     "%s | %d | %s | error : %s\n | errno = %d(%s) \n", 
                     (const char*)__FILE__, __LINE__, __FUNCTION__, msg.c_str(), errno, std::strerror(errno));
            perror(message);
            
            if(should_exit)
            {
                exit(EXIT_FAILURE);
            }
            return false;
        } 
        return true;
    }

bool test(){
    int ret = 0;
    
    // 1. 创建套接字
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    ret_check(socket_fd, "socket failed");

    // 2. 准备地址结构 & 绑定地址
    struct sockaddr_in server_addr = {0};
    server_addr.sin_family = AF_INET;
    //server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");   // 监听特定IP
    server_addr.sin_addr.s_addr = INADDR_ANY;             // 监听所有接口（推荐）
    server_addr.sin_port = htons(8080);

    // 注意结构体名称，是sock_addr*而不是sockaddr
    ret = bind(socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    ret_check(ret, "bind failed");

    // 3. 监听连接
    ret = listen(socket_fd, 5);
    ret_check(ret, "listen failed");

    printf("Server listening on port 8080...\n");

    // 4. [关键缺失]必须添加accept()循环，否则服务器会立即退出
    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);
    while(true)
    {
        int client_fd = accept(socket_fd, (struct sockaddr*)&client_addr, &client_len);
        ret_check(client_fd, "accept failed");

        // 处理客户端连接
        printf("Client connected: %s:%d\n", 
               inet_ntoa(client_addr.sin_addr),
               ntohs(client_addr.sin_port));

        // 向客户端发送欢迎消息
        const char* msg = "Hello, client!";
        send(client_fd, msg, strlen(msg), 0);

        close(client_fd);   // 处理完后关闭客户端套接字
    }

    close(socket_fd);
    return 0;
}

int main()
{
    test();
    return 0;
}

